package com.blockmeta.bbs.businesslibrary.widget

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.blockmeta.bbs.baselibrary.utils.CalculateUtil
import com.blockmeta.bbs.baselibrary.utils.DimentionsUtil
import com.blockmeta.bbs.businesslibrary.R

/**
 * @author AirThor
 * @date 2019/9/24.
 */
class DebateBar : View {
    /** vs图标 */
    lateinit var mVSBitmap: Bitmap
    /** 红色激活态支持按钮 */
    lateinit var mRedActivedBtn: Bitmap
    /** 红色非激活态支持按钮 */
    lateinit var mRedDefaultBtn: Bitmap
    /** 蓝色激活态支持按钮 */
    lateinit var mBlueActivedBtn: Bitmap
    /** 蓝色非激活态支持按钮 */
    lateinit var mBlueDefaultBtn: Bitmap
    /** 按钮点击回调 */
    var onVoteBarClickListener: OnVoteBarClickListener? = null

    private val mRedGradientStartColor = Color.parseColor("#F23D3D")
    private val mRedGradientEndColor = Color.parseColor("#EE0000")
    private val mDarkRedColor = Color.parseColor("#C70000")
    private val mBlueGradientStartColor = Color.parseColor("#3F82DE")
    private val mBlueGradientEndColor = Color.parseColor("#035BD4")
    private val mDarkBlueColor = Color.parseColor("#024CB1")

    private val DP8 = DimentionsUtil.dp2px(8f)
    private val DP4 = DimentionsUtil.dp2px(4f)
    private val DP2 = DimentionsUtil.dp2px(2f)

    private val mTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val mRedPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val mBluePaint = Paint(Paint.ANTI_ALIAS_FLAG)
    lateinit var mRedGradient: LinearGradient
    lateinit var mBlueGradient: LinearGradient

    /** 两个按钮点击的有效区域 */
    private val mRedBtnRegion = Region()
    private val mBlueBtnRegion = Region()

    private val mRedBtnRect = Rect()
    private val mRedBtnActiveRect = Rect()
    private val mRedBtnDefaultRect = Rect()
    private val mBlueBtnRect = Rect()
    private val mBlueBtnActiveRect = Rect()
    private val mBlueBtnDefaultRect = Rect()
    private var mTotalStripWidth = 0
    private val mTextRect = Rect()
    private val mVSRect = Rect()

    private var mOldPercent = 0.5
    private var mTargetPercent = 0.5

    var mRedCount = 0
    private set(value) {
        field =value
    }
    var mBlueCount = 0
    private set(value) {
        field = value
    }
    /** 按钮的各种状态 */
    private val STATE_RED_DEFAULT = 1
    private val STATE_RED_ACTIVE = 1 shl 1
    private val STATE_BLUE_DEFAULT= 1 shl 2
    private val STATE_BLUE_ACTIVE= 1 shl 3
    /** 当前状态 */
    private var mCurrentState = STATE_RED_DEFAULT or STATE_RED_DEFAULT

    private var mTextBaseLine = 0f

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)

    private var redClick = false
    private var blueClick = false

    init {
        mTextPaint.color = Color.parseColor("#FFFFFF")
        mTextPaint.textSize = DimentionsUtil.dp2px(12f).toFloat()
        mRedPaint.style = Paint.Style.FILL
        mBluePaint.style = Paint.Style.FILL
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        mVSBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.icon_vs)
        mRedDefaultBtn = BitmapFactory.decodeResource(context.resources, R.drawable.btn_red_default)
        mRedActivedBtn = BitmapFactory.decodeResource(context.resources, R.drawable.btn_red_actived)
        mBlueDefaultBtn = BitmapFactory.decodeResource(context.resources, R.drawable.btn_blue_default)
        mBlueActivedBtn = BitmapFactory.decodeResource(context.resources, R.drawable.btn_blue_actived)
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        mVSBitmap.recycle()
        mRedDefaultBtn.recycle()
        mRedActivedBtn.recycle()
        mBlueDefaultBtn.recycle()
        mBlueActivedBtn.recycle()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)

        val width=View.getDefaultSize(widthSize,widthMeasureSpec)
        val height = View.getDefaultSize(heightSize,heightMeasureSpec)

        setMeasuredDimension(width,height)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        val btnSideLength = h-DP2-DP4-paddingTop-paddingBottom
        mRedBtnActiveRect.set(paddingLeft,paddingTop+DP4,paddingLeft+btnSideLength,h-paddingBottom-DP2)
        mRedBtnDefaultRect.set(paddingLeft,paddingTop,paddingLeft+btnSideLength,h-paddingBottom-DP2)

        mBlueBtnActiveRect.set(w-paddingRight-btnSideLength,paddingTop+DP4,w-paddingRight,h-paddingBottom-DP2)
        mBlueBtnDefaultRect.set(w-paddingRight-btnSideLength,paddingTop,w-paddingRight,h-paddingBottom-DP2)

        mTotalStripWidth = w-paddingLeft-paddingRight-DP8*2
        mTextBaseLine = paddingTop+DP4+((height-paddingBottom-DP8-DP4-paddingTop)-(mTextPaint.fontMetrics.bottom-mTextPaint.fontMetrics.top))/2-mTextPaint.fontMetrics.top

        mRedGradient = LinearGradient(0f,0f,0f,(height-paddingBottom-DP8-DP2).toFloat(),mRedGradientStartColor,mRedGradientEndColor,Shader.TileMode.CLAMP)
        mBlueGradient = LinearGradient(0f,0f,0f,(height-paddingBottom-DP8-DP2).toFloat(),mBlueGradientStartColor,mBlueGradientEndColor,Shader.TileMode.CLAMP)
    }

    override fun onDraw(canvas: Canvas) {
        var midPoint = CalculateUtil.mul(mTotalStripWidth.toDouble(),mTargetPercent).toFloat()
        midPoint += paddingLeft + DP8
        val minLeft = mRedBtnActiveRect.right+DP8*2+getTextWidth(mRedCount.toString())+(height-paddingTop-paddingBottom)/2
        val maxRight = mBlueBtnActiveRect.left-DP8*2-getTextWidth(mBlueCount.toString())-(height-paddingTop-paddingBottom)/2
        midPoint = when {
            midPoint<minLeft -> minLeft.toFloat()
            midPoint>maxRight -> maxRight.toFloat()
            else -> midPoint
        }
        mRedPaint.color = mDarkRedColor
        mRedPaint.shader = null
        canvas.drawRect((paddingLeft+DP8).toFloat(), (paddingTop+DP4).toFloat(),midPoint, (height-paddingBottom-DP2).toFloat(),mRedPaint)
        mRedPaint.shader = mRedGradient
        canvas.drawRect((paddingLeft+DP8).toFloat(), (paddingTop+DP4).toFloat(),midPoint, (height-paddingBottom-DP2-DP8).toFloat(),mRedPaint)

        mBluePaint.color = mDarkBlueColor
        mBluePaint.shader = null
        canvas.drawRect(midPoint,(paddingTop+DP4).toFloat(), (width-paddingRight-DP8).toFloat(),(height-paddingBottom-DP2).toFloat(),mBluePaint)
        mBluePaint.shader = mBlueGradient
        canvas.drawRect(midPoint,(paddingTop+DP4).toFloat(), (width-paddingRight-DP8).toFloat(),(height-paddingBottom-DP2-DP8).toFloat(),mBluePaint)

        canvas.drawBitmap(getRedBitmapByState(),null,mRedBtnRect, null)
        canvas.drawBitmap(getBlueBitmapByState(), null,mBlueBtnRect,null)

        val vsLeft = midPoint - (height-paddingTop-paddingBottom)/2
        val vsTop = paddingTop
        val vsRight = midPoint + (height-paddingTop-paddingBottom)/2
        val vsBottom = height - paddingBottom
        mVSRect.set(vsLeft.toInt(),vsTop, vsRight.toInt(),vsBottom)
        canvas.drawBitmap(mVSBitmap,null,mVSRect,null)

        mTextPaint.textAlign = Paint.Align.LEFT
        canvas.drawText(mRedCount.toString(), (mRedBtnRect.right+DP8).toFloat(),mTextBaseLine,mTextPaint)
        mTextPaint.textAlign = Paint.Align.RIGHT
        canvas.drawText(mBlueCount.toString(), (mBlueBtnRect.left-DP8).toFloat(),mTextBaseLine,mTextPaint)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val motionEvent=event.actionMasked

        when (motionEvent) {
            MotionEvent.ACTION_DOWN -> {
                redClick = mRedBtnRegion.contains(event.x.toInt(), event.y.toInt())
                blueClick = mBlueBtnRegion.contains(event.x.toInt(),event.y.toInt())
            }
            MotionEvent.ACTION_UP -> {
                redClick = redClick && mRedBtnRegion.contains(event.x.toInt(), event.y.toInt())
                blueClick = blueClick && mBlueBtnRegion.contains(event.x.toInt(),event.y.toInt())
                if (redClick&&(mCurrentState and STATE_RED_ACTIVE != STATE_RED_ACTIVE)){
                    if(onVoteBarClickListener!=null){
                        onVoteBarClickListener!!.onVoteBarClickListener(this,Button.RED,true)
                    }
                }else if (blueClick&&(mCurrentState and STATE_BLUE_ACTIVE != STATE_BLUE_ACTIVE)){
                    if (onVoteBarClickListener!=null){
                        onVoteBarClickListener!!.onVoteBarClickListener(this,Button.BLUE,true)
                    }
                }
            }
        }
        return redClick||blueClick||super.onTouchEvent(event)
    }

    /**
     * 设置支持数
     */
    fun setVoteCounts(redCount: Int,blueCount: Int){
        mRedCount = if (redCount<0) 0 else redCount
        mBlueCount = if (blueCount<0) 0 else blueCount

        mTargetPercent = if (mRedCount==0&&mBlueCount==0){0.5}else{CalculateUtil.div(redCount.toDouble(),(redCount+blueCount).toDouble(),2)}

        invalidate()
    }

    private fun getTextWidth(text: String): Int{
        mTextPaint.getTextBounds(text,0,text.length,mTextRect)
        return mTextRect.width()
    }

    private fun getRedBitmapByState(): Bitmap{
        return if (mCurrentState and STATE_RED_ACTIVE != STATE_RED_ACTIVE){
            mRedBtnRect.set(mRedBtnDefaultRect)
            mRedBtnRegion.set(mRedBtnRect)
            mRedDefaultBtn
        }else{
            mRedBtnRect.set(mRedBtnActiveRect)
            mRedBtnRegion.set(mRedBtnRect)
            mRedActivedBtn
        }
    }

    private fun getBlueBitmapByState(): Bitmap{
        return if (mCurrentState and STATE_BLUE_ACTIVE != STATE_BLUE_ACTIVE){
            mBlueBtnRect.set(mBlueBtnDefaultRect)
            mBlueBtnRegion.set(mBlueBtnRect)
            mBlueDefaultBtn
        }else{
            mBlueBtnRect.set(mBlueBtnActiveRect)
            mBlueBtnRegion.set(mBlueBtnRect)
            mBlueActivedBtn
        }
    }

    enum class Button{
        RED,BLUE
    }

    /**
     * 设置按钮状态同时更新支持数
     */
    fun setActiveAndUpdateCount(button: Enum<Button>,active: Boolean){
        when(button){
            Button.RED -> {
                mRedCount = if (active) {
                    mBlueCount =
                    if (mCurrentState and STATE_BLUE_ACTIVE == STATE_BLUE_ACTIVE) --mBlueCount else mBlueCount
                    ++mRedCount
                } else {
                    --mRedCount
                }
                setState(if(active) STATE_RED_ACTIVE else STATE_RED_DEFAULT)
                setVoteCounts(mRedCount,mBlueCount)
            }

            Button.BLUE -> {
                mBlueCount = if (active) {
                    mRedCount =
                            if (mCurrentState and STATE_RED_ACTIVE == STATE_RED_ACTIVE) --mRedCount else mRedCount
                    ++mBlueCount
                } else {
                    --mBlueCount
                }
                setState(if(active) STATE_BLUE_ACTIVE else STATE_BLUE_DEFAULT)
                setVoteCounts(mRedCount,mBlueCount)
            }
        }
    }
    /**
     * 设置按钮状态
     */
    fun setActive(button: Enum<Button>,active: Boolean){
        when(button){
            Button.RED -> {
                setState(if(active) STATE_RED_ACTIVE else STATE_RED_DEFAULT)
            }

            Button.BLUE -> {
                setState(if(active) STATE_BLUE_ACTIVE else STATE_BLUE_DEFAULT)
            }
        }
        invalidate()
    }

    fun resetState(){
        mCurrentState = STATE_BLUE_DEFAULT and STATE_RED_DEFAULT
        invalidate()
    }
    /**
     * 设置按钮状态
     */
    private fun setState(state: Int){
        mCurrentState = when (state) {
            STATE_RED_ACTIVE -> mCurrentState or state or STATE_BLUE_DEFAULT and
                    STATE_BLUE_ACTIVE.inv() and STATE_RED_DEFAULT.inv()

            STATE_BLUE_ACTIVE -> mCurrentState or state or STATE_RED_DEFAULT and
                    STATE_RED_ACTIVE.inv() and STATE_BLUE_DEFAULT.inv()

            STATE_RED_DEFAULT -> mCurrentState or state and STATE_RED_ACTIVE.inv()

            STATE_BLUE_DEFAULT -> mCurrentState or state and STATE_BLUE_ACTIVE.inv()

            else -> mCurrentState
        }
    }

    interface OnVoteBarClickListener{
        fun onVoteBarClickListener(debateBar: DebateBar,view: Enum<Button>,active: Boolean)
    }
}